package com.czk.server;

import com.alibaba.fastjson.JSON;
import com.czk.domain.*;
import com.czk.utils.CacheUtil;
import com.czk.utils.FileUtil;
import com.czk.utils.MsgUtil;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;

import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * @Author:ChenZhangKun
 * @Date: 2021/4/23 10:32
 */
public class MySeverChannelHandler extends ChannelInboundHandlerAdapter {
    @Override
    public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
        super.handlerAdded(ctx);
    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {

    }

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        // 拿到客户端通道
        Channel channel = ctx.channel();
        System.out.println("链接报告开始");
        System.out.println("链接报告信息：有一客户端链接到本服务端。channelId：" + channel.id());
        System.out.println("链接报告IP:" + channel.localAddress());
        System.out.println("链接报告Port:" + channel.localAddress());
        System.out.println("链接报告完毕");
        // 通知客户端链接建立成功
        String str = "通知客户端链接建立成功" + " " + new Date() + " " + channel.localAddress() + "\r\n";
        ctx.writeAndFlush(str);
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        // 数据格式验证
        if (!(msg instanceof FileTransferProtocol)) {
            return;
        }
        // 强转
        FileTransferProtocol fileTransferProtocol = (FileTransferProtocol) msg;
        // 0传输文件'请求'、1文件传输'指令'、2文件传输'数据'
        switch (fileTransferProtocol.getTransferType()) {
            case 0:
                // 拿到传输文件数据
                Object transferObj = fileTransferProtocol.getTransferObj();
                if (!(transferObj instanceof FileDescInfo)) {
                    return;
                }
                // 强转
                FileDescInfo fileDescInfo = (FileDescInfo) transferObj;
                // 端点续传信息 生产实际需要保存数据库
                FileBurstInstruct fileBurstInstruct = CacheUtil.burstDataMap.get(fileDescInfo.getFileName());
                // 是否由缓存
                if (null != fileBurstInstruct) {
                    // 是否上传完毕
                    if (fileBurstInstruct.getStatus() == Constants.FileStatus.COMPLETE) {
                        // 移除缓存
                        CacheUtil.burstDataMap.remove(fileDescInfo.getFileName());
                    }
                    System.out.println(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()) + " 服务端，接收客户端传输文件请求[断点续传]。" );
                    // 写回客户端
                    ctx.writeAndFlush(MsgUtil.buildTransferInstruct(fileBurstInstruct));
                    break;
                }
                //发送信息
                FileTransferProtocol sendFileTransferProtocol = MsgUtil.buildTransferInstruct(Constants.FileStatus.BEGIN, fileDescInfo.getFileUrl(), 0);
                ctx.writeAndFlush(sendFileTransferProtocol);
                System.out.println(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()) + " 服务端，接收客户端传输文件请求。" );
                break;
            case 2:
                // 拿到传输的文件
                FileBurstData fileBurstData=(FileBurstData)fileTransferProtocol.getTransferObj();
                // 写文件
                FileBurstInstruct burstInstruct = FileUtil.writeFile("E:\\", fileBurstData);
                // 保存信息
                CacheUtil.burstDataMap.put(fileBurstData.getFileName(),burstInstruct);
                // 写回客户端
                ctx.writeAndFlush(MsgUtil.buildTransferInstruct(burstInstruct));
                System.out.println(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()) + " 服务端，接收客户端传输文件数据。" );
                if (burstInstruct.getStatus()==Constants.FileStatus.COMPLETE){
                    // 结束
                    CacheUtil.burstDataMap.remove(fileBurstData.getFileName());
                }
                break;
            default:
                break;
        }
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        super.exceptionCaught(ctx, cause);
    }
}
